package com.koron.device.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.koron.bean.base.Response;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.DateAndTimeUtils;
import com.koron.common.core.util.ExportExcelUtil;
import com.koron.device.bean.Equipment;
import com.koron.device.bean.EquipmentParams;
import com.koron.device.bean.ExportParamMsgBean;
import com.koron.device.bean.bo.TypeParamJsBo;
import com.koron.device.bean.bo.TypeParamsJs;
import com.koron.device.bean.template.EquipmentJsMsg;
import com.koron.device.bean.template.EquipmentJsTemplate;
import com.koron.device.bean.template.ImPMsgDto;
import com.koron.device.mapper.EquipmentMapper;
import com.koron.device.mapper.TypeParamsMapper;
import com.koron.device.service.ParamimpService;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author qingfeng
 * @description: TODO
 * @date 2021/7/12 20:29
 */
@Service
public class ParamImpServiceImpl implements ParamimpService {

    @Autowired
    private EquipmentServiceImpl equipmentservice;

    @Override
    @TaskAnnotation("exportJsParam")
    public List<EquipmentJsTemplate> exportJsParam(SessionFactory factory, String eqId) {

        EquipmentMapper mapper = factory.getMapper(EquipmentMapper.class);

        List<ExportParamMsgBean> paramlist = mapper.queryParamJsEq(eqId);
        List<EquipmentJsTemplate> eqlist = mapper.queryParamJsEqMain(eqId);

        cn.hutool.core.lang.Assert.isFalse(eqlist.size() > equipmentservice.MAXQTY, "请缩小导出范围");

        // 设备所有技术参数值
        Map<String, List<ExportParamMsgBean>> eqidParammap = paramlist.stream().collect(Collectors.groupingBy(ExportParamMsgBean::getId));

        // 说有技术参数
        List<TypeParamsJs> tpjslist = factory.getMapper(TypeParamsMapper.class).queryAllJs();

        Map<String, List<TypeParamsJs>> typeParammap = tpjslist.stream().collect(Collectors.groupingBy(TypeParamsJs::getTypeId));

        for (EquipmentJsTemplate equipmentJsTemplate : eqlist) {
            StringBuffer jsStr = new StringBuffer();
            String typeId = equipmentJsTemplate.getTypeId();

            // 设备类型对应的所有技术参数
            List<TypeParamsJs> jslist = typeParammap.get(typeId);

            if (CollUtil.isEmpty(jslist)) {
                continue;
            }

            // 设备对应技术参数值
            List<ExportParamMsgBean> jsValuelist = eqidParammap.get(equipmentJsTemplate.getEqId());
            Map<String, String> paramIdValuemap = new HashMap();
            if (CollUtil.isNotEmpty(jsValuelist)) {
//                paramIdValuemap = jsValuelist.stream().filter(j -> StrUtil.isNotBlank(j.getParamId())).collect(Collectors.toMap(ExportParamMsgBean::getParamId, ExportParamMsgBean::getParamValue));
                paramIdValuemap = jsValuelist.stream().filter(j -> StrUtil.isNotBlank(j.getParamId()))
                        .collect(HashMap::new, (map, exportparammsgbean)-> map.put(exportparammsgbean.getParamId(), exportparammsgbean.getParamValue()), HashMap::putAll);
            }

            List<TypeParamJsBo> bolist = new ArrayList();
            for (TypeParamsJs js : jslist) {
                String s = paramIdValuemap.get(js.getId());
                if (StrUtil.isBlank(s)) {
                    bolist.add(new TypeParamJsBo(js.getParamName(), "\\"));
                    continue;
                }
                bolist.add(new TypeParamJsBo(js.getParamName(), s));
            }
            if (CollUtil.isNotEmpty(bolist)) {
                jsStr.append(bolist.stream().map(TypeParamJsBo::getCombination).collect(Collectors.joining("、")));
            } else {
                jsStr.append("");
            }
            equipmentJsTemplate.setJsParam(jsStr.toString());
        }

        return eqlist;
    }

    @Override
    @TaskAnnotation("importJsParam")
    public Response importJsParam(SessionFactory factory, List<EquipmentJsMsg> excellist, String fileName) {

        EquipmentMapper mapper = factory.getMapper(EquipmentMapper.class);

        if (CollUtil.isEmpty(excellist)) {
            return Response.ok("无数据导入");
        }
        List<String> eqids = excellist.stream().map(EquipmentJsTemplate::getEqId).collect(Collectors.toList());
        // 所有设备现有参数
        List<EquipmentParams> equipmentParams = mapper.queryByEquipmentIdIn(eqids);
        List<Equipment> eqlist = mapper.queryByIdIn(eqids);
        HashMap<String, String> eqTypeIdmap = new HashMap<>();
        for (Equipment equipment : eqlist) {
            eqTypeIdmap.put(equipment.getId(), equipment.getTypeId());
        }

        // 所有技术参数
        List<TypeParamsJs> tpjslist = factory.getMapper(TypeParamsMapper.class).queryAllJs();

        List<EquipmentParams> insertlist = new ArrayList<>();
        List<EquipmentParams> updatelist = new ArrayList<>();

        for (EquipmentJsMsg equipmentJsMsg : excellist) {
            equipmentJsMsg.setErrorMsg(null); // 重置错误信息
            String eqId = equipmentJsMsg.getEqId();
            String typeId = eqTypeIdmap.get(eqId);
            String jsParam = equipmentJsMsg.getJsParam();

            if (StrUtil.isBlank(jsParam)) {
                // 该设备类型没有技术参数
                continue;
            }

            // 设备分类对应的技术参数
            List<TypeParamsJs> typeJsParam = tpjslist.stream().filter(j -> j.getTypeId().equals(typeId)).collect(Collectors.toList());

            // 设备现在有参数
            List<EquipmentParams> eqparamlist = equipmentParams.stream().filter(f -> f.getEquipmentId().equals(eqId)).collect(Collectors.toList());
            Map<String, List<EquipmentParams>> paramIdObjmap = eqparamlist.stream().collect(Collectors.groupingBy(EquipmentParams::getParamId));

            List<String> paramkvlist = StrUtil.split(jsParam, "、");
            for (String kv : paramkvlist) {
                String kvtrim = StrUtil.trim(kv);
                List<String> split = StrUtil.split(kvtrim, ":");
                if (split.size() != 2) {
                    equipmentJsMsg.setErrorMsg(StrUtil.format("{} 技术参数格式不合规范; ", equipmentJsMsg.getErrorMsg()));
                    continue;
                }
                String paramK = split.get(0);
                String paramV = split.get(1);
                if (paramV.equals("\\")) {
                    // 约定为空字符"\"
                    continue;
                }
                boolean paramexist = typeJsParam.stream().allMatch(p -> !p.getParamName().equals(paramK));
                if (paramexist) {
                    equipmentJsMsg.setErrorMsg(StrUtil.format("{} 该设备类型没有【{}】技术参数; ", equipmentJsMsg.getErrorMsg(), paramK));
                    continue;
                }
                TypeParamsJs typeParamsJs = typeJsParam.stream().filter(f -> f.getParamName().equals(paramK)).findFirst().get();

                String dataType = typeParamsJs.getDataType();
                if (dataType.equals("date")) {
                    String formatDate = DateAndTimeUtils.converExcelDate(paramV);
                    boolean legalDate = DateAndTimeUtils.isLegalDate(formatDate.length(), formatDate, "yyyy-MM-dd");
                    if (!legalDate) {
                        equipmentJsMsg.setErrorMsg(StrUtil.format("{} 【{}】参数日期格式不正确; ", equipmentJsMsg.getErrorMsg(), paramK));
                        continue;
                    }
                }
                if (dataType.equals("number")) {
                    if (!NumberUtil.isNumber(paramV)) {
                        equipmentJsMsg.setErrorMsg(StrUtil.format("{} 【{}】参数只能是数字格式; ", equipmentJsMsg.getErrorMsg(), paramK));
                        continue;
                    }
                }
                if (ObjectUtil.isNotNull(typeParamsJs.getDataLength())) {
                    if (paramV.length() > typeParamsJs.getDataLength()) {
                        equipmentJsMsg.setErrorMsg(StrUtil.format("{} 【{}】参数值长度不允许超过{}; ", equipmentJsMsg.getErrorMsg(), paramK, typeParamsJs.getDataLength()));
                        continue;
                    }
                }

                EquipmentParams eqparam = new EquipmentParams();
                eqparam.setId(CodeTools.getCode32());
                eqparam.setDataSources(DateUtil.now() + "-参数导入-" + fileName);
                eqparam.setEquipmentId(eqId);
                eqparam.setParamId(typeParamsJs.getId());
                eqparam.setParamValue(paramV);
                if (paramIdObjmap.keySet().contains(typeParamsJs.getId())) {
                    String id = paramIdObjmap.get(typeParamsJs.getId()).get(0).getId();
                    eqparam.setId(id);
                    updatelist.add(eqparam);
                } else {
                    insertlist.add(eqparam);
                }
            }

        }

        List<EquipmentJsMsg> msglist = excellist.stream().filter(m -> StrUtil.isNotBlank(m.getErrorMsg())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(msglist)) {
            String time = String.valueOf(DateUtil.currentSeconds());
            String path = ExportExcelUtil.saveExcel(excellist, EquipmentJsMsg.class, StrUtil.format("错误信息{}.xls", time));
            return Response.ok(new ImPMsgDto("ERROR", "导入异常", path));
        }

        // 保存设备参数
        equipmentservice.batchSaveEquipemntParams(updatelist, insertlist, factory);

        return Response.ok(new ImPMsgDto("SUCCESS", "导入更新成功", null));
    }
}
